﻿using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;

namespace Kugar.ERPFramework.Core.Entity
{

    public interface IEntity:ICloneable
    {
        //ConcurrentDictionary<string, object> Fields { get; }
        //Dictionary<string, ICollection> Details { get; }
        EntityState EntityState { get; }
        void BeginInitValue();
        void EndInitValue();

        object GetValue(string propertyName);
        T GetValue<T>(string propertyName);

        void SetValue(string propertyName, object value);
    }

    [Serializable]
    public class EntityBase:IEntity, INotifyPropertyChanged, IEquatable<EntityBase>,ICloneable
    {
        private ConcurrentDictionary<string, object> _fields = new ConcurrentDictionary<string, object>();
        private Dictionary<string,ICollection> _details =new Dictionary<string,ICollection>();
        private EntityState _entityState = EntityState.Normal;
        private static Lazy<Type[]> _knownType = new Lazy<Type[]>(buildKnownType);

        [NonSerialized]
        private bool _isIniting = false; //标识当前是否处于初始化状态

        public EntityBase()
        {
            _entityState = EntityState.Normal;
        }

       
        /// <summary>
        ///     该实体所包含的所有实体字段
        /// </summary>
        public ConcurrentDictionary<string, object> Fields { get { return _fields; } }

        /// <summary>
        ///     该实体包含的所有明细表
        /// </summary>
        public Dictionary<string, ICollection> Details { get { return _details; } }

        /// <summary>
        ///     实体的当前状态
        /// </summary>
        public EntityState EntityState { get { return _entityState; } protected set { _entityState = value; } }

        /// <summary>
        ///     开始初始化值,从调用该函数后,对实体所做的修改,不会影响EntityState属性
        /// </summary>
        public void BeginInitValue()
        {
            _isIniting = true;
        }

        /// <summary>
        ///     结束初始化值,调用该函数后,对实体所做的修改,将开始影响EntityState属性
        /// </summary>
        public void EndInitValue()
        {
            _isIniting = false;
        }

        public object GetValue(string propertyName)
        {
            return getFieldValue(propertyName);
        }

        public T GetValue<T>(string propertyName)
        {
            return getFieldValue<T>(propertyName);
        }

        public void SetValue(string propertyName, object value)
        {
            setFieldValue(propertyName, value);
        }

        /// <summary>
        ///     返回创建一个新的对象,,如需预先赋值的,可重载该函数
        /// </summary>
        /// <returns></returns>
        public static EntityBase CreateNew()
        {
            return  new EntityBase();
        }

        #region Clone members
        public virtual object Clone()
        {
            var temp = new EntityBase();

            foreach (var field in _fields)
            {
                temp.setFieldValue(field.Key,field.Value is ICloneable? ((ICloneable)field.Value).Clone():field.Value);
            }

            return temp;
        }
        #endregion


        #region Equality members

        public bool Equals(EntityBase other)
        {
            if (other==null)
            {
                return false;
            }

            var srcKeys = _fields.Keys;
            var desKeys = other.Fields.Keys;

            if (this._fields.Count!=other.Fields.Count)
            {
                return false;
            }

            if (this.Details.Count != other.Details.Count)
            {
                return false;
            }

            foreach (var key in desKeys)
            {
                if (!srcKeys.Contains(key))
                {
                    return false;
                }
            }

            foreach (var key in srcKeys)
            {
                if (!desKeys.Contains(key))
                {
                    return false;
                }
            }

            foreach (var field in _fields)
            {
                object v;

                if (other.Fields.TryGetValue(field.Key,out  v))
                {
                    if (v != null && field.Value != null && !field.Value.Equals(v))
                    {
                        return false;
                    }
                    else if(v==null && field.Value==null)
                    {
                        continue;
                    }
                    else if (v==null || field.Value==null)
                    {
                        return false;
                    }
                }
            }

            //TODO:验证明细列表
            for (int i = 0; i < this.Details.Count; i++)
            {
               // var detail=this.Details[]
            }

            return true;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != this.GetType()) return false;
            return Equals((EntityBase) obj);
        }

        public override int GetHashCode()
        {
            throw new NotImplementedException();
        }



        public static bool operator ==(EntityBase left, EntityBase right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(EntityBase left, EntityBase right)
        {
            return !Equals(left, right);
        }

        #endregion


        /// <summary>
        ///     设置指定字段的值
        /// </summary>
        /// <param name="propName">指定字段名称</param>
        /// <param name="value">指定字段将设置的值</param>
        protected void setFieldValue(string propName,object value)
        {
            object oldValue;
            bool isChanged = false;

            if (_fields.TryGetValue(propName,out oldValue))
            {
                if (oldValue!=null && !oldValue.Equals(value))
                {
                    _fields[propName] = value;
                    isChanged = true;
                }
                else if(oldValue==null && value!=null)
                {
                    _fields[propName] = value;
                    isChanged = true;
                }
            }
            else
            {
                _fields.TryAdd(propName,value);
                isChanged = true;
            }

            if (isChanged && !_isIniting)
            {
                EntityState = EntityState.Normal;
                OnPropertyChanged(propName);
            }
        }

        /// <summary>
        ///     获取指定名称的字段值
        /// </summary>
        /// <param name="propName">指定的字段名称</param>
        /// <param name="defaultValue">如果尚未初始化该字段值,则返回该参数指定的默认值</param>
        /// <returns>返回字段对应的值</returns>
        protected object getFieldValue(string propName,object defaultValue=null)
        {
            object value;

            if (_fields.TryGetValue(propName,out value))
            {
                return value;
            }
            else
            {
                return defaultValue;
            }
        }

        protected T getFieldValue<T> (string propName)
        {
            return getFieldValue<T>(propName, default(T));
        }

        /// <summary>
        ///     获取指定名称的字段值,返回一个泛型值
        /// </summary>
        /// <param name="propName">指定的字段名称</param>
        /// <param name="defaultValue">如果尚未初始化该字段值,则返回该参数指定的默认值</param>
        /// <returns>返回字段对应的值</returns>
        protected T getFieldValue<T> (string propName,object defaultValue)
        {
            var value = this.getFieldValue(propName,defaultValue);

            return (T) value;
        }


        #region INotifyPropertyChanged 接口实现

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion


        [Obsolete("该函数由WCF调用")]
        public Type[] GetKnownTypes()
        {
            return _knownType.Value;
        }

        private static Type[] buildKnownType()
        {
            var assemblys = AppDomain.CurrentDomain.GetAssemblies();

            var lst = new List<Type>();

            foreach (var  assembly in assemblys)
            {
                var types = assembly.GetTypes();

                lst.AddRange(types.Where(x=>x.IsSubclassOf(typeof(EntityBase))));
            }

            return lst.ToArray();
        }

        #region IExtensibleDataObject 接口实现

        public ExtensionDataObject ExtensionData { get; set; }

        #endregion
    }


    //[Serializable]
    //public class EntityViewModelBase:IEntity
    //{
    //    private EntityState _state= EntityState.Normal;
    //    private Dictionary<string,EntityBase> _cacheEntity=new Dictionary<string, EntityBase>(3);



    //    public EntityViewModelBase(EntityBase originalEntity)
    //    {
    //        _originalEntity = originalEntity;
    //    }

    //    public void RegistrEntity(string entityName, EntityBase entity)
    //    {
    //        _cacheEntity.Add(entityName,entity);
    //    }

    //    public EntityState EntityState
    //    {
    //        get
    //        {
    //            if (_originalEntity.EntityState== EntityState.Normal && _state== EntityState.Normal)
    //            {
    //                return EntityState.Normal;
    //            }
    //            else if (_originalEntity.EntityState== EntityState.Normal && _state!= EntityState.Normal)
    //            {
    //                return _state;
    //            }
    //            else
    //            {
    //                return _originalEntity.EntityState;
    //            }
    //        }
    //    }

    //    public void BeginInitValue()
    //    {
    //        _originalEntity.BeginInitValue();
    //    }

    //    public void EndInitValue()
    //    {
    //        _originalEntity.EndInitValue();
    //    }

    //    public object GetValue(string propertyName)
    //    {
    //        throw new NotImplementedException();
    //    }

    //    public T GetValue<T>(string propertyName)
    //    {
    //        throw new NotImplementedException();
    //    }

    //    public void SetValue(string propertyName, object value)
    //    {
    //        throw new NotImplementedException();
    //    }

    //    public object Clone()
    //    {
    //        return null;
    //    }
    //}

    public enum EntityState
    {
        Normal,
        Modify,
        Deleted
    }
}
